#ifndef H_ARRAY

#define H_ARRAY

#include "./Status.h"

namespace	Platform
{

	namespace	Common
	{

		template<typename TElementType, DWORD number>
		class	TArray
		{
		public:
			TArray(){}
			TArray(const TArray &object){(*this) = object;}
			TArray& operator=(const TArray &object)
			{
				if (this != &object)
				{
					m_element[number] = object.m_element[number];
					m_status = object.m_status;
				}
				return (*this);
			}
			bool operator==(const TArray &object)
			{
				if (this != &object)
				{
					if (number != object.count())
					{
						return false;
					}
					if (m_status != object.m_status)
					{
						return false;
					}
					for (int iCount = 0; iCount < number; ++iCount)
					{
						if (m_element[iCount] != object.m_element[iCount])
						{
							return false;
						}
					}
				}
				return true;
			}
			TElementType& operator[](const int index)
			{
				return m_element[index];
			}
			~TArray(){}
		public:
			int initialize()
			{
				int iResult = m_status.initialize(eObjectStatusIdle);
				if (RETURN_CHECK_FAILED(iResult))
				{
					return RETURN_FAILED;
				}
				return RETURN_SUCCESS;
			}
			int allocation(OUT DWORD &index)
			{
				for (int count = 0; count < number; count++)
				{
					if (RETURN_SUCCESS(m_status.equal(count, eObjectStatusIdle)))
					{
						index = count;
						m_status.set(count, eObjectStatusBusy);
						return RETURN_SUCCESS;
					}
				}
				return RETURN_FAILED;
			}
			int allocation(OUT DWORD &index, IN const TElementType *object)
			{
				if (RETURN_CHECK_FAILED(allocation(index)))
				{
					return RETURN_FAILED;
				}
				m_element[index] = (*object);
				return RETURN_SUCCESS;
			}
			int free(IN DWORD index)
			{
				if (RETURN_CHECK_FAILED(m_status.equal(index, eObjectStatusBusy)))
				{
					return RETURN_FAILED;
				}
				m_status.set(index, eObjectStatusIdle);
				return RETURN_SUCCESS;
			}
			int element(IN DWORD index, OUT TElementType **object)
			{
				if (RETURN_CHECK_FAILED(m_status.equal(index, eObjectStatusBusy)))
				{
					return RETURN_FAILED;
				}
				(*object) = m_element[index];
				return RETURN_SUCCESS;
			}
			int element(OUT DWORD &index, IN TElementType *object)
			{
				for (int count = 0; count < number; count++)
				{
					if (RETURN_SUCCESS(m_status.equal(index, eObjectStatusBusy)))
					{
						if ((*object) == m_element[count])
						{
							index = count;
							return RETURN_SUCCESS;
						}
					}
				}
				return RETURN_FAILED;
			}
			int used(OUT DWORD &index)
			{
				index = 0;
				for (int count = 0; count < number; count++)
				{
					if (RETURN_SUCCESS(m_status.equal(index, eObjectStatusBusy)))
					{
						index++;
					}
				}
				return RETURN_SUCCESS;
			}
			int is_idle(IN DWORD index)
			{
				return m_status.equal(index, eObjectStatusIdle);
			}
			int count()
			{
				return number;
			}
			int destroy()
			{
				return initialize();
			}
		private:
			TElementType							m_element[number];
			TStatus<eObjectStatus, number>			m_status;
		};

	}

}

#endif
